package com.kaifamiao.ajax.controller;

import com.alibaba.fastjson2.JSONObject;
import com.kaifamiao.ajax.entity.Student;
import com.kaifamiao.ajax.exception.ServiceException;
import com.kaifamiao.ajax.service.StudentService;
import com.kaifamiao.ajax.service.impl.StudentServiceImpl;
import com.mysql.cj.util.StringUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.tinylog.Logger;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@WebServlet("/student/*")
public class StudentServlet extends HttpServlet {

    private StudentService service = new StudentServiceImpl();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Logger.trace("设置响应的MIME类型");
        // 设置响应头中 content-type 字段 (即设置MIME类型)
        resp.setContentType( "text/plain;charset=UTF-8");
        // 请务必记得调用重写的service方法 (因为父类中的service会根据HTTP动作分发请求)
        super.service(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        PrintWriter out = resp.getWriter();

        String sid = req.getParameter( "id" );

        if(StringUtils.isNullOrEmpty(sid) || StringUtils.isEmptyOrWhitespaceOnly(sid)) {
            Logger.trace("查询所有学生信息");
            // 查询数据库中所有的学生
            List<Student> list = service.loadAll();
            // 将Map转换成JSON格式字符串
            String json = JSONObject.toJSONString(Map.of( "students", list ));
            out.println( json );
            return;
        }

        Logger.trace("查询编号为" + sid + "的学生信息");
        Long id = Long.valueOf(sid);
        Student student = service.load(id);
        String json = JSONObject.toJSONString(Map.of( "student", student == null ? "" : student ));
        out.println( json );
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        final PrintWriter out = resp.getWriter();
        final Map<String,Object> map = new HashMap<>();
        Student s;
        // 获得本次请求的MIME类型(即从请求头中获取content-type字段的值)
        final String mimeType = req.getContentType();
        Logger.trace( mimeType );
        // 若本次请求正文中包含的是JSON格式的数据
        if( "application/json".equals( mimeType ) ) {
            StringBuilder sb = new StringBuilder();
            BufferedReader br = req.getReader();
            String line;
            while( ( line = br.readLine() ) != null ){
                sb.append( line );
            }
            String json = sb.toString();
            Logger.trace( json );
            s = JSONObject.parseObject(json, Student.class);
        } else {
            s = new Student();
            s.setName(req.getParameter( "name" ));
            s.setGender(req.getParameter( "gender" ));
            String text = req.getParameter( "birthdate" );
            try {
                LocalDate birthdate = LocalDate.parse(text);
                s.setBirthdate(birthdate);
            } catch (Exception e) {
                Logger.error( e, "出生日期格式错误");
                map.put("success", false);
                map.put("message", "出生日期格式错误");
                out.println( JSONObject.toJSONString( map ) );
                return;
            }
            s.setHometown(req.getParameter( "hometown" ));
        }

        try {
            boolean res = service.save(s);
            if( res ) {
                Logger.trace("保存成功");
                map.put("success", true);
                map.put("message", "保存成功");
            } else {
                Logger.trace("保存失败");
                map.put( "success", false );
                map.put( "message", "保存失败" );
            }
        }
        // 捕获在Service中显式抛出的异常
        catch (ServiceException e) {
            Logger.error( e, "学生信息保存失败" );
            map.put( "success", false );
            map.put( "message", "保存失败" );
            map.put( "cause", e.getMessage() );
        }
        // 捕获除ServiceException之外的其它异常
        catch (Exception e) {
            Logger.error( e, "学生信息保存失败" );
            map.put( "success", false );
            map.put( "message", "保存失败" );
            map.put( "cause", e.getMessage() );
        }

        out.println( JSONObject.toJSONString( map ) );
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        Map<String,Object> map = new HashMap<>();

        Student s;
        // 获得本次请求的MIME类型(即从请求头中获取content-type字段的值)
        final String mimeType = req.getContentType();
        Logger.trace( mimeType );
        // 若本次请求正文中包含的是JSON格式的数据
        if( "application/json".equals( mimeType ) ) {
            StringBuilder sb = new StringBuilder();
            BufferedReader br = req.getReader();
            String line;
            while( ( line = br.readLine() ) != null ){
                sb.append( line );
            }
            String json = sb.toString();
            Logger.trace( json );
            s = JSONObject.parseObject(json, Student.class);
        } else {
            s = new Student();
            try {
                BeanUtils.populate(s, req.getParameterMap());
            } catch (Exception ex) {
                Logger.error(ex, "数据封装失败");
                map.put("success", false);
                map.put("message", "卧槽，出错了");
                out.println(JSONObject.toJSONString(map));
                return;
            }

            String text = req.getParameter("dateOfBirth");
            try {
                LocalDate birthdate = LocalDate.parse(text);
                s.setBirthdate(birthdate);
            } catch (Exception e) {
                Logger.error(e, "保存失败");
                map.put("success", false);
                map.put("message", "出生日期格式错误");
                out.println(JSONObject.toJSONString(map));
                return;
            }
        }

        try {
            boolean res = service.update(s);
            map.put("success", res);
            map.put("message", res ? "修改成功" : "修改失败" );
            Logger.trace( res ? "修改成功" : "修改失败" );
        } catch (Exception e) {
            Logger.error(e, "修改失败");
            map.put("success", false);
            map.put("message", "修改失败");
            map.put("cause", e.getMessage());
        }

        out.println( JSONObject.toJSONString( map ) );
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        Map<String,Object> map = new HashMap<>();

        String sid = req.getParameter( "id" );
        if( StringUtils.isNullOrEmpty(sid) || StringUtils.isEmptyOrWhitespaceOnly(sid) ){
            map.put("success", false);
            map.put("message", "被删除学生编号不能为空");
            Logger.trace("被删除学生编号不能为空");
            out.println( JSONObject.toJSONString( map ) );
            return;
        }

        Long id = null;
        try {
            id = Long.valueOf(sid);
        } catch (Exception e ) {
            Logger.error(e, "学生编号必须是整数形式");
            map.put("success", false);
            map.put("message", "学生编号必须是整数形式");
            out.println( JSONObject.toJSONString( map ) );
            return;
        }

        try {
            boolean res = service.remove(id);
            if(res) {
                map.put("success", true);
                map.put("message", "删除成功");
                Logger.trace( "删除成功" );
            } else {
                map.put("success", false);
                map.put("message", "删除失败");
                Logger.trace( "删除失败" );
            }
        } catch (Exception e) {
            Logger.error(e, "学生信息删除失败");
            map.put("success", false);
            map.put("message", "删除失败");
            map.put("cause", e.getMessage());
        }

        out.println( JSONObject.toJSONString( map ) );
    }
}
